﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using DTcms.Core.API.Filters;
using DTcms.Core.Common.Emum;
using DTcms.Core.Common.Extensions;
using DTcms.Core.Common.Helper;
using DTcms.Core.IServices;
using DTcms.Core.Model.Models;
using DTcms.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace DTcms.Core.API.Controllers
{
    /// <summary>
    /// 文章投稿
    /// </summary>
    [Area("api")]
    [Route("api/article/contribute")]
    [ApiController]
    public class ArticleContributeController : ControllerBase
    {
        private readonly IArticleContributeService _articleContributeService;
        private readonly IUserService _userService;
        private readonly IMapper _mapper;
        private readonly ISiteService _siteService;
        private readonly ISiteChannelService _siteChannelService;

        public ArticleContributeController(IArticleContributeService articleContributeService,
            IUserService userService,
            ISiteService siteService,
            ISiteChannelService siteChannelService,
            IMapper mapper)
        {
            _articleContributeService = articleContributeService;
            _userService = userService;
            _mapper = mapper;
            _siteService = siteService;
            _siteChannelService = siteChannelService;
        }

        /// <summary>
        /// 获取总记录数量
        /// 示例：/api/article/contribute/view/count
        /// </summary>
        [HttpGet("view/count")]
        [Authorize]
        public async Task<IActionResult> GetCount([FromQuery] BaseParameter searchParam)
        {
            var result = await _articleContributeService.QueryCountAsync(x => searchParam.Status < 0 || x.Status == searchParam.Status);
            //返回成功200
            return Ok(result);
        }

        /// <summary>
        /// 根据ID获取数据
        /// 示例：/api/article/contribute/1/1
        /// </summary>
        [HttpGet("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.View, "channelId")]
        public async Task<IActionResult> GetById([FromRoute] long id, [FromQuery] BaseParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _articleContributeService.QueryAsync<ArticleContribute>(x => x.Id == id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            //使用AutoMapper转换成ViewModel，根据字段进行塑形
            var result = _mapper.Map<ArticleContributeDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 根据ID获取数据
        /// 示例：/api/article/contribute/1/1/view
        /// </summary>
        [HttpGet("{channelId}/{id}/view")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.View, "channelId")]
        public async Task<IActionResult> GetByIdView([FromRoute] long id, [FromQuery] BaseParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _articleContributeService.QueryAsync<ArticleContribute>(x => x.Id == id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            //使用AutoMapper转换成ViewModel，根据字段进行塑形
            var result = _mapper.Map<ArticleContributeViewDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取指定数量列表
        /// 示例：/api/article/contribute/view/10
        /// </summary>
        [HttpGet("view/{top}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.View, "channelId")]
        public async Task<IActionResult> GetList([FromRoute] int top, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _articleContributeService.QueryListAsync<ArticleContribute>(top,
                x => searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true,
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "Status,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticleContributeDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }

        /// <summary>
        /// 获取分页列表
        /// 示例：/api/article/contribute/1?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.View, "channelId")]
        public async Task<IActionResult> GetList([FromQuery] BaseParameter searchParam, [FromQuery] PageParamater pageParam, [FromRoute] long channelId)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表，如果ID大于0则查询该用户下所有的列表
            var list = await _articleContributeService.QueryPageAsync<ArticleContribute>(
                pageParam.PageSize,
                pageParam.PageIndex,
                x => (searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true)
                && (searchParam.Keyword.IsNotNullOrEmpty() ? x.UserName.Contains(searchParam.Keyword) : true)
                &&x.ChannelId== channelId,
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "Status,-Id");
            if (list == null || list.Count() <= 0)
            {
                return NotFound(ResponseMessage.Error("暂无查询到记录"));
            }

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticleContributeDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 添加一条记录
        /// 示例：/api/article/contribute/1
        /// </summary>
        [HttpPost("{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.Add, "channelId")]
        public async Task<IActionResult> Add([FromBody] ArticleContributeAddDto modelDto)
        {
            //验证数据是否合法
            if (!TryValidateModel(modelDto))
            {
                return ValidationProblem(ModelState);
            }
            SiteChannel siteChannel = await _siteChannelService.QueryAsync<SiteChannel>(x => x.Id == modelDto.ChannelId);
            //检查频道是否存在
            if (siteChannel==null)
            {
                return NotFound(ResponseMessage.Error($"频道{modelDto.ChannelId}不存在或已删除"));
            }
            //检查是否可以投稿
            if (siteChannel.IsContribute==0)
            {
                return NotFound(ResponseMessage.Error($"该频道不允许投稿"));
            }
            modelDto.SiteId = siteChannel.SiteId;
            //检查站点是否存在
            if (!await _siteService.ExistsAsync<Sites>(x => x.Id == modelDto.SiteId))
            {
                return NotFound(ResponseMessage.Error($"站点{modelDto.SiteId}不存在或已删除"));
            }
            
            //获取当前用户名
            modelDto.UserId = await _userService.GetUserIdAsync();
            modelDto.UserName = await _userService.GetUserNameAsync();
            //映射成实体
            var dtoModel = _mapper.Map<ArticleContribute>(modelDto);
            dtoModel.AddTime = DateTime.Now;
            //写入数据库
            var mapModel = await _articleContributeService.AddAsync(dtoModel);
            //映射成DTO再返回，否则出错
            var result = _mapper.Map<ArticleContributeDto>(mapModel);
            return Ok(result);
        }

        /// <summary>
        /// 修改一条记录
        /// 示例：/api/article/contribute/1/1
        /// </summary>
        [HttpPut("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.Edit, "channelId")]
        public async Task<IActionResult> Update([FromRoute] long id, [FromBody] ArticleContributeEditDto modelDto)
        {
            //验证数据是否合法
            if (!TryValidateModel(modelDto))
            {
                return ValidationProblem(ModelState);
            }
            var user = await _userService.GetUserAsync();
            modelDto.UpdateBy = user.UserName;
            var result = await _articleContributeService.UpdateAsync(modelDto.Id,modelDto);
            return NoContent();
        }

        /// <summary>
        /// 局部更新一条记录
        /// 示例：/api/article/contribute/1/1
        /// Body：[{"op":"replace","path":"/title","value":"new title"}]
        /// </summary>
        [HttpPatch("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.Edit, "channelId")]
        public async Task<IActionResult> Update([FromRoute] long id, [FromBody] JsonPatchDocument<ArticleContributeEditDto> patchDocument)
        {
            var model = await _articleContributeService.QueryAsync<ArticleContribute>(x => x.Id == id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }

            var modelToPatch = _mapper.Map<ArticleContributeEditDto>(model);
            patchDocument.ApplyTo(modelToPatch, ModelState);
            //验证数据是否合法
            if (!TryValidateModel(modelToPatch))
            {
                return ValidationProblem(ModelState);
            }
            //更新操作AutoMapper替我们完成，只需要调用保存即可
            _mapper.Map(modelToPatch, model);
            await _articleContributeService.SaveAsync();

            return NoContent();
        }

        /// <summary>
        /// 删除一条记录
        /// 示例：/api/article/contribute/1/1
        /// </summary>
        [HttpDelete("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.Delete, "channelId")]
        public async Task<IActionResult> Delete([FromRoute] long id)
        {
            if (!await _articleContributeService.ExistsAsync<ArticleContribute>(x => x.Id == id))
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            var result = await _articleContributeService.DeleteAsync<ArticleContribute>(x => x.Id == id);

            return NoContent();
        }

        /// <summary>
        /// 批量删除记录
        /// 示例：/api/article/contribute/1?ids=1,2,3
        /// </summary>
        [HttpDelete("{channelId}")]
        [Authorize]
        [AuthorizeFilter("ArticleContribute", ActionType.Delete, "channelId")]
        public async Task<IActionResult> DeleteByIds([FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var arrIds = Ids.ToIEnumerable<long>();
            if (arrIds == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //执行批量删除操作
            await _articleContributeService.DeleteAsync<ArticleContribute>(x => arrIds.Contains(x.Id));

            return NoContent();
        }

        #region 前端调用接口
        /// <summary>
        /// 根据ID获取数据
        /// 示例：/api/client/article/contribute/1
        /// </summary>
        [HttpGet("/api/client/article/contribute/{id}")]
        [Authorize]
        public async Task<IActionResult> ClientGetById([FromRoute] long id, [FromQuery] BaseParameter param)
        {
            var user = await _userService.GetUserAsync();
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _articleContributeService.QueryAsync<ArticleContribute>(x => x.Id == id&&x.UserId==user.Id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            //使用AutoMapper转换成ViewModel，根据字段进行塑形
            var result = _mapper.Map<ArticleContributeDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取指定数量列表
        /// 示例：/api/client/article/contribute/view/10
        /// </summary>
        [HttpGet("/api/client/article/contribute/view/{top}")]
        [Authorize]
        public async Task<IActionResult> ClientGetList([FromRoute] int top, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            var userId = await _userService.GetUserIdAsync();
            //获取数据库列表
            var resultFrom = await _articleContributeService.QueryListAsync<ArticleContribute>(top,
                x => x.UserId == userId
                && (!searchParam.Keyword.IsNotNullOrEmpty() || x.Title.Contains(searchParam.Keyword)),
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "Status,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticleContributeDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }

        /// <summary>
        /// 获取分页列表
        /// 示例：/client/article/contribute?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("/api/client/article/contribute")]
        [Authorize]
        public async Task<IActionResult> ClientGetList([FromQuery] BaseParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            var user = await _userService.GetUserAsync();
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticleContributeDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表，如果ID大于0则查询该用户下所有的列表
            var list = await _articleContributeService.QueryPageAsync<ArticleContribute>(
                pageParam.PageSize,
                pageParam.PageIndex,
                x => x.UserId == user.Id
                && (!searchParam.Keyword.IsNotNullOrEmpty() || x.Title.Contains(searchParam.Keyword)),
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "Status,-Id");
            if (list == null || list.Count() <= 0)
            {
                return NotFound(ResponseMessage.Error("暂无查询到记录"));
            }

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticleContributeDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 添加一条记录
        /// 示例：/api/client/article/contribute
        /// </summary>
        [HttpPost("/api/client/article/contribute")]
        [Authorize]
        public async Task<IActionResult> ClientAdd([FromBody] ArticleContributeAddDto modelDto)
        {
            //验证数据是否合法
            if (!TryValidateModel(modelDto))
            {
                return ValidationProblem(ModelState);
            }
            SiteChannel siteChannel = await _siteChannelService.QueryAsync<SiteChannel>(x => x.Id == modelDto.ChannelId);
            //检查频道是否存在
            if (siteChannel == null)
            {
                return NotFound(ResponseMessage.Error($"频道{modelDto.ChannelId}不存在或已删除"));
            }
            //检查是否可以投稿
            if (siteChannel.IsContribute == 0)
            {
                return NotFound(ResponseMessage.Error($"该频道不允许投稿"));
            }
            modelDto.SiteId = siteChannel.SiteId;
            //检查站点是否存在
            if (!await _siteService.ExistsAsync<Sites>(x => x.Id == modelDto.SiteId))
            {
                return NotFound(ResponseMessage.Error($"站点{modelDto.SiteId}不存在或已删除"));
            }

            //获取当前用户名
            modelDto.UserId = await _userService.GetUserIdAsync();
            modelDto.UserName = await _userService.GetUserNameAsync();
            //映射成实体
            var dtoModel = _mapper.Map<ArticleContribute>(modelDto);
            dtoModel.AddTime = DateTime.Now;
            //写入数据库
            var mapModel = await _articleContributeService.AddAsync(dtoModel);
            //映射成DTO再返回，否则出错
            var result = _mapper.Map<ArticleContributeDto>(mapModel);
            return Ok(result);
        }

        /// <summary>
        /// 修改一条记录
        /// 示例：/api/client/article/contribute/1
        /// </summary>
        [HttpPut("/api/client/article/contribute/{id}")]
        [Authorize]
        public async Task<IActionResult> ClientUpdate([FromRoute] long id, [FromBody] ArticleContributeEditDto modelDto)
        {
            //验证数据是否合法
            if (!TryValidateModel(modelDto))
            {
                return ValidationProblem(ModelState);
            }
            var user = await _userService.GetUserAsync();
            modelDto.UserId = user.Id;
            modelDto.UserName = user.UserName;
            modelDto.UpdateBy = user.UserName;
            var result = await _articleContributeService.UserUpdateAsync(modelDto.Id, modelDto);
            return NoContent();
        }

        /// <summary>
        /// 删除一条记录
        /// 示例：/api/client/article/contribute/1
        /// </summary>
        [HttpDelete("/api/client/article/contribute/{id}")]
        [Authorize]
        public async Task<IActionResult> ClientDelete([FromRoute] long id)
        {
            var user = await _userService.GetUserAsync();
            if (!await _articleContributeService.ExistsAsync<ArticleContribute>(x => x.Id == id&&x.UserId==user.Id))
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            var result = await _articleContributeService.DeleteAsync<ArticleContribute>(x => x.Id == id);

            return NoContent();
        }

        /// <summary>
        /// 批量删除记录
        /// 示例：/api/client/article/contribute?ids=1,2,3
        /// </summary>
        [HttpDelete("/api/client/article/contribute")]
        [Authorize]
        public async Task<IActionResult> ClientDeleteByIds([FromQuery] string Ids)
        {
            var user = await _userService.GetUserAsync();
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var arrIds = Ids.ToIEnumerable<long>();
            if (arrIds == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //执行批量删除操作
            await _articleContributeService.DeleteAsync<ArticleContribute>(x => arrIds.Contains(x.Id)&&x.UserId==user.Id);

            return NoContent();
        }
        #endregion
    }
}
